<?php

// 公共助手函数

//----------------------RickyFlex---------------------------//
if (!function_exists('success_ful')) {
    function success_ful($message, $data = '')
    {
        return ['status' => 1, 'message' => $message, 'data' => $data];
    }
}
if (!function_exists('error_ful')) {
    function error_ful($message, $data = "")
    {
        return ['status' => 0, 'message' => $message, 'data' => $data];
    }
}

if (!function_exists('randstr')) {
    /**
     * 获得随机字符串
     * @param $len             需要的长度
     * @param $special        是否需要特殊符号
     * @return string       返回随机字符串
     */
    function randstr($len = 10, $special = false)
    {
        $chars = array(
            "a",
            "b",
            "c",
            "d",
            "e",
            "f",
            "g",
            "h",
            "i",
            "j",
            "k",
            "l",
            "m",
            "n",
            "o",
            "p",
            "q",
            "r",
            "s",
            "t",
            "u",
            "v",
            "w",
            "x",
            "y",
            "z",
            "A",
            "B",
            "C",
            "D",
            "E",
            "F",
            "G",
            "H",
            "I",
            "J",
            "K",
            "L",
            "M",
            "N",
            "O",
            "P",
            "Q",
            "R",
            "S",
            "T",
            "U",
            "V",
            "W",
            "X",
            "Y",
            "Z",
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9"
        );

        if ($special) {
            $chars = array_merge(
                $chars,
                array(
                    "!",
                    "@",
                    "#",
                    "$",
                    "?",
                    "|",
                    "{",
                    "/",
                    ":",
                    ";",
                    "%",
                    "^",
                    "&",
                    "*",
                    "(",
                    ")",
                    "-",
                    "_",
                    "[",
                    "]",
                    "}",
                    "<",
                    ">",
                    "~",
                    "+",
                    "=",
                    ",",
                    "."
                )
            );
        }

        $charsLen = count($chars) - 1;
        shuffle($chars);                            //打乱数组顺序
        $str = '';
        for ($i = 0; $i < $len; $i++) {
            $str .= $chars[mt_rand(0, $charsLen)];    //随机取出一位
        }
        return $str;
    }
}

if (!function_exists('build_encrypt')) {
    /**
     * 数据脱敏函数
     * @param $string 需要脱敏值
     * @param int $start 开始
     * @param int $length 结束
     * @param string $re 脱敏替代符号
     * @return bool|string
     * 例子:
     * build_encrypt('13126989876', 3, 4); //131****9876
     * build_encrypt('张三四', 0, -1); //**四
     */
    function build_encrypt($string, $start = 3, $length = 4, $re = '*')
    {
        //备份原值
        $back = $string;

        if (empty($string)) {
            return false;
        }

        $strarr = [];
        $mb_strlen = mb_strlen($string);

        //循环把 字符串 变为数组
        while ($mb_strlen) {
            $strarr[] = mb_substr($string, 0, 1, 'utf8');
            $string = mb_substr($string, 1, $mb_strlen, 'utf8');
            $mb_strlen = mb_strlen($string);
        }

        $strlen = count($strarr);
        $begin = $start >= 0 ? $start : ($strlen - abs($start));
        $end = $last = $strlen - 1;
        if ($length > 0) {
            $end = $begin + $length - 1;
        } elseif ($length < 0) {
            $end -= abs($length);
        }

        for ($i = $begin; $i <= $end; $i++) {
            $strarr[$i] = $re;
        }

        if ($begin >= $end || $begin >= $last || $end > $last)
            return $back;
        return implode('', $strarr);
    }
}

if (!function_exists('build_code')) {
    /**
     * 生成唯一订单号
     * @param string $prefix 指定的订单前缀
     * @return string  返回字符串
     */

    function build_code($prefix = "")
    {
        @date_default_timezone_set("PRC");
        $order_id_main = date('YmdHis') . rand(10000, 99999);
        //订单号码主体长度
        $order_id_len = strlen($order_id_main);
        $order_id_sum = 0;
        for ($i = 0; $i < $order_id_len; $i++) {
            $order_id_sum += (int) (substr($order_id_main, $i, 1));
        }
        //唯一订单号码（YYYYMMDDHHIISSNNNNNNNNCC）
        $osn = $prefix . $order_id_main . str_pad((100 - $order_id_sum % 100) % 100, 2, '0', STR_PAD_LEFT); //生成唯一订单号
        return $osn;
    }
}

if (!function_exists('file_upload')) {
    /**
     * 单文件上传
     * @param string $path  文件储存文件夹路径，默认为应用根目录下的uploads文件夹
     * @return array status是执行状态，成功为true,失败为false,message是状态提示，file_name是保存的文件名路径
     */
    function file_upload($path = '')
    {
        $arr = [
            'status'    =>  false,
            'message'   =>  '上传中',
            'file_name'      =>  ''
        ];
        if (isset($_FILES['files']) && $_FILES['files']['error'] === UPLOAD_ERR_OK) {

            $tmp_path = $_FILES['files']['tmp_name'];   //临时文件路径
            $origin_name = $_FILES['files']['name'];   //原始文件名
            $file_size = $_FILES['files']['size'];      //文件大小(字节)
            $mime_type = $_FILES['files']['type'];      //MIME类型
            
            // 验证文件类型
            // application/x-zip-compressed-zip application/x-msdownload-exe
            $allowed_mime_type = [
                'image/jpeg',
                'image/jpg',
                'image/png',
                'text/plain',
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'application/vnd.ms-excel',
                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            ];
            $allowed_extension = ['jpg', 'jpeg', 'png', 'txt', 'pdf', 'doc', 'docx', 'xls', 'xlsx'];
            $extension = strtolower(pathinfo($origin_name, PATHINFO_EXTENSION));    //真实后缀名
            // if($extension === 'doc'){
            //     $extension = 'docx';
            // }
            // if($extension === 'xls'){
            //     $extension = 'xlsx';
            // }
            $base_name = basename($origin_name,'.' . $extension);

            // 文件类型双重验证
            if (!in_array($mime_type, $allowed_mime_type)) {
                error_log("非法扩展名: {$extension}，文件名: {$origin_name}");

                $arr['message'] = "不支持的文件类型{$extension}";
                return $arr;
            }
            if (!in_array($extension, $allowed_extension)) {
                error_log("非法扩展名: {$extension}，文件名: {$origin_name}");
                $arr['message'] = "不支持的文件类型{$extension}";
                return $arr;
            }
            // 验证真实的文件类型（防篡改）
            // $finfo = new finfo(FILEINFO_MIME_TYPE);
            // $real_mime = $finfo->file($tmp_path);
            // if (!in_array($real_mime, $allowed_mime_type)) {
            //     error_log("非法扩展名: {$real_mime}（声明类型: {$_FILES['files']['type']}），文件名: {$origin_name}");

            //     $arr['message'] = "不支持的文件类型{$extension}";
            //     return $arr;
            // }

            // 验证文件大小(应用层限制)
            $max_size = 50 * 1024 * 1024;    //  50M
            if ($file_size > $max_size) {
                error_log("文件过大: {$file_size}字节（最大允许{$max_size}字节）");
                $arr['message'] = '文件大小超过限制(最大50MB)';
                return $arr;
            }

            // 生成安全文件名(防止路径遍历)
            // $safe_name = uniqid(mt_rand()) . '.' . $extension;

            
            //生成更难以猜测的文件名，减少被猜测的风险
            $safe_name = bin2hex(random_bytes(16)) . '.' . $extension;

            // 移动文件到目标目录
            // $domain = $this->request->domain();
            // 确保以斜杠/结尾
            $target_dir = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/' . $path;

            // 验证文件夹是否存在,不存在则创建
            if (!is_dir($target_dir)) {
                mkdir($target_dir, 0755, true);
            }
            $target_path =  $target_dir . $safe_name;

            // 验证临时文件是否存在
            if (!is_uploaded_file($tmp_path)) {
                error_log("临时文件不存在或非上传文件: {$tmp_path}");
                $arr['message'] = '文件上传失败：临时文件异常';
                return $arr;
            }

            
            // 移动文件
            if (move_uploaded_file($tmp_path, $target_path)) {
                $arr['status'] = true;
                $arr['message'] = '上传成功';
                $arr['file_name'] = $path . $safe_name;
                $arr['origin_name'] = $origin_name;
                $arr['file_size'] = $file_size;
                $arr['extension'] = $extension;
                $arr['base_name'] = $base_name;
                
                return $arr;
            } else {
                error_log("文件移动失败: 临时路径={$tmp_path}，目标路径={$target_path}");
                $arr['message'] = '文件移动失败';
                return $arr;
            }
        } else {
            // 处理错误
            $error_messages = [
                UPLOAD_ERR_INI_SIZE => '文件超过PHP配置大小限制',
                UPLOAD_ERR_FORM_SIZE => '文件超过表单MAX_FILE_SIZE限制',
                UPLOAD_ERR_PARTIAL => '文件上传不完整',
                UPLOAD_ERR_NO_FILE => '未选择文件',
            ];
            $error_code = $_FILES['files']['error'] ?? UPLOAD_ERR_NO_FILE;
            $user_msg = $error_messages[$error_code] ?? "未知上传错误（错误码: {$error_code}）";

            error_log("上传失败: 错误码={$error_code}");

            $arr['message'] = "上传失败: 错误码={$user_msg},提示:{$user_msg}";
            return $arr;
        }
    }
}
